#include <Config\ParserFileName.h>
#include <Config\OptionChan.h>
#include <regex>
#include <string>
#include <iostream>
#include <fstream>
#include <algorithm>
#include <exception>

#pragma warning(disable : 4996)
double freqchart[] = {
	8.1757989156, 8.661957218, 9.1770239974, 10.3008611535, 10.3008611535, 10.9133822323, 11.5623257097, 12.2498573744, 12.9782717994, 13.75, 14.5676175474, 15.4338531643,
	16.3515978313, 17.3239144361, 18.3540479948, 19.4454364826, 20.6017223071, 21.8267644646, 23.1246514195, 24.4997147489, 25.9565435987, 27.5, 29.1352350949, 30.8677063285,
	32.7031956626, 34.6478288721, 36.7080959897, 38.8908729653, 41.2034446141, 43.6535289291, 46.249302839, 48.9994294977, 51.9130871975, 55, 58.2704701898, 61.735412657,
	65.4063913251, 69.2956577442, 73.4161919794, 77.7817459305, 82.4068892282, 87.3070578583, 92.4986056779, 97.9988589954, 103.826174395, 110, 116.5409403795, 123.470825314,
	130.8127826503, 138.5913154884, 146.8323839587, 155.563491861, 164.8137784564, 174.6141157165, 184.9972113558, 195.9977179909, 207.65234879, 220, 233.081880759, 246.9416506281,
	261.6255653006, 277.1826309769, 293.6647679174, 311.1269837221, 329.6275569129, 349.228231433, 369.9944227116, 391.9954359817, 415.3046975799, 440, 466.1637615181, 493.8833012561,
	523.2511306012, 554.3652619537, 587.3295358348, 622.2539674442, 659.2551138257, 698.456462866, 739.9888454233, 783.9908719635, 830.6093951599, 880, 932.3275230362, 987.7666025122,
	1046.5022612024, 1108.7305239075, 1174.6590716696, 1244.5079348883, 1318.5102276515, 1396.912925732, 1479.9776908465, 1567.981743927, 1661.2187903198, 1760, 1864.6550460724, 1975.5332050245,
	2093.0045224048, 2217.461047815, 2349.3181433393, 2489.0158697766, 2637.020455303, 2793.825851464, 2959.9553816931, 3135.963487854, 3322.4375806396, 3520, 3729.3100921447, 3951.066410049,
	4186.0090448096, 4434.92209563, 4698.6362866785, 4978.0317395533, 5274.0409106059, 5587.6517029281, 5919.9107633862, 5919.9107633862, 6644.8751612791, 7040, 7458.6201842894, 7902.132820098,
	8372.0180896192, 8869.8441912599, 9397.272573357, 9956.0634791066, 10548.0818212118, 11175.3034058561, 11839.8215267723, 12543.853951416
};
char * midichart[] = {
	"C-2", "C#-2", "D-2", "D#-2", "E-2", "F-2", "F#-2", "G-2", "G#-2", "A-2", "A#-2", "B-2",
	"C-1", "C#-1", "D-1", "D#-1", "E-1", "F-1", "F#-1", "G-1", "G#-1", "A-1", "A#-1", "B-1",
	"C0", "C#0", "D0", "D#0", "E0", "F0", "F#0", "G0", "G#0", "A0", "A#0", "B0",
	"C1", "C#1", "D1", "D#1", "E1", "F1", "F#1", "G1", "G#1", "A1", "A#1", "B1",
	"C2", "C#2", "D2", "D#2", "E2", "F2", "F#2", "G2", "G#2", "A2", "A#2", "B2",
	"C3", "C#3", "D3", "D#3", "E3", "F3", "F#3", "G3", "G#3", "A3", "A#3", "B3",
	"C4", "C#4", "D4", "D#4", "E4", "F4", "F#4", "G4", "G#4", "A4", "A#4", "B4",
	"C5", "C#5", "D5", "D#5", "E5", "F5", "F#5", "G5", "G#5", "A5", "A#5", "B5",
	"C6", "C#6", "D6", "D#6", "E6", "F6", "F#6", "G6", "G#6", "A6", "A#6", "B6",
	"C7", "C#7", "D7", "D#7", "E7", "F7", "F#7", "G7", "G#7", "A7", "A#7", "B7",
	"C8", "C#8", "D8", "D#8", "E8", "F8", "F#8", "G8",
	"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11",
	"12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23",
	"24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35",
	"36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47",
	"48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59",
	"60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "70", "71",
	"72", "73", "74", "75", "76", "77", "78", "79", "80", "81", "82", "83",
	"84", "85", "86", "87", "88", "89", "90", "91", "92", "93", "94", "95",
	"96", "97", "98", "99", "100", "101", "102", "103", "104", "105", "106", "107",
	"108", "109", "110", "111", "112", "113", "114", "115", "116", "117", "118", "119",
	"120", "121", "122", "123", "124", "125", "126", "127"
};
double mtof(const char *midinote){//midi to frequency
	int i = 0;

	for (; i < 256; i++){
		if (strcmp(midichart[i], midinote) == 0){
			break;
		}
	}
	if (i > 127){ i -= 128; }

	if (i >= 0 && i < 127){
		return freqchart[i];
	}

	return -1;
}

double mtofoffset(const char * midinote, int offset){
	int i = 0;

	for (; i < 256; i++){
		if (strcmp(midichart[i], midinote) == 0){
			break;
		}
	}
	if (i > 127){ i -= 128; }

	if (i >= 0 && i < 127){
		return freqchart[i + offset];
	}
	return -1;
}
PaserName::PaserName(std::string path){
	valid = False;
	if (path.length() > 0){
		valid = True;
	}
	std::regex matchFile("\"?(.+\\\\)?(.+)(\\.[\\w\\d]+).*\"?\\n?");
	std::regex matchMidi("n=((?:\\d{1,3})|(?:[A-Za-z]#?\\-?\\d))");
	std::regex matchmidiOffset("o=(-?\\d+)");
	std::regex matchCh("ch=(\\d+)");
	std::regex matchFS("fs=(\\d+)");
	std::regex matchWarp("w=(\\d+)");
	std::string pathname = std::regex_replace(path, matchFile, "$1");
	pathName = std::regex_replace(path, matchFile, "$1$2$3");

	try {
		
		std::string filename = std::regex_replace(path, matchFile, "$2");
		std::string midinoteArg = std::regex_replace(path, matchMidi, "$1", std::regex_constants::format_no_copy);
		std::string midiOffsetArg = std::regex_replace(path, matchmidiOffset, "$1", std::regex_constants::format_no_copy);
		std::string channelArg = std::regex_replace(path, matchCh, "$1", std::regex_constants::format_no_copy);
		std::string framesizeArg = std::regex_replace(path, matchFS, "$1", std::regex_constants::format_no_copy);
		std::string warpArg = std::regex_replace(path, matchWarp, "$1", std::regex_constants::format_no_copy); //change here

		if (midinoteArg.length()>0) {
			initFreq = mtof(midinoteArg.c_str());
			if (midiOffsetArg.length() > 0){
				initFreq = mtofoffset(midinoteArg.c_str(), atoi(midiOffsetArg.c_str()));
			}
		}
		if (warpArg.length() > 0) {
			initFreq = atoi(warpArg.c_str());
		}

		// Get framesize for pitch detection
		blocksize = 4096;
		if (framesizeArg != "") blocksize = atoi(framesizeArg.c_str());
		else {
			if (initFreq >= 50) blocksize = 4096;
			if (initFreq >= 100) blocksize = 2048;
			if (initFreq >= 200) blocksize = 1024;
			if (initFreq >= 400) blocksize = 512;
			if (initFreq >= 800) blocksize = 256;
		}

		
	}
	catch (...){
		valid = False;
	}


	std::regex match("(.+\\\\)?(.+)(\\.[\\w\\d]+)");

	dir = std::regex_replace(pathName, match, "$1");
	name = std::regex_replace(pathName, match, "$2");
	ext = std::regex_replace(pathName, match, "$3");

}
std::string PaserName::getDir(){
	return dir;
}
std::string PaserName::getName(){
	return name;
}
std::string PaserName::getExt(){
	return ext;
}
float PaserName::getInitFreq(){
	return initFreq;
}
std::string PaserName::getPath(){
	return pathName;
}

int PaserName::isValid(){
	return valid;
}


DataChannel* PaserName::GetInfoChan(DataChannel *dataChan){
	OptionHelmholtz* data = (OptionHelmholtz *)dataChan;
	data->initFrequency = initFreq;
	data->BlockSize = blocksize;
	return dataChan;
}



ListFile::ListFile(){
	valid = True;
}
int ListFile::load(std::string path){
		FILE* file = NULL;
		int files = 0;
		char tmpName[2000] = { 0 };
		file = fopen(path.c_str(), "r");

		if (file != NULL){
			while (fgets(tmpName, 2000, file) != NULL){
				listfiles.push_back( std::string(tmpName)); 
			}
		}
		else{
			printf("Open file: %s error, file does not exist \n", path);
			valid =  False;
			
		}

		if (file != NULL)
			fclose(file);

		valid =  True;
		return valid;
}
int ListFile::size(){
	return listfiles.size();
}
PaserName ListFile::operator[](unsigned int post){
	if (post < listfiles.size() && post >= 0){
		return PaserName(listfiles[post]);
	}
	else{
		return PaserName("");
	}
}